home *** CD-ROM | disk | FTP | other *** search
/ Amiga Magazin: Amiga-CD 1997 May & June / Amiga-CD 1997 #5-6.iso / emulatoren / frodov2.4 / src / 6581.asm < prev    next >
Assembly Source File  |  1996-12-08  |  10KB  |  533 lines

  1. *
  2. * 6581.asm - SID-Emulation
  3. *
  4. * Copyright (C) 1994-1996 by Christian Bauer
  5. *
  6.  
  7. *
  8. * Anmerkungen:
  9. * ------------
  10. *
  11. * Funktionsprinzip:
  12. *  - Es bestehen vier Möglichkeiten zur SID-Emulation, die über das
  13. *    Flag UseSIDCard ausgewählt werden: Keine Emulation (d.h. kein Ton),
  14. *    die Verwendung der SID-Karte, die "6581sid.library" und die
  15. *    "playsid.library"
  16. *
  17. * SID-Karte:
  18. *  - Die SID-Karte enthält einen echten C64-SID, der im Adreßraum
  19. *    $a00001-$a00039 (Register an den ungeraden Adressen) eingeblendet
  20. *    ist (z.B. auf einer Zorro-II-Karte)
  21. *  - Wegen Timing-Problemen mit der Karte werden Lesezugriffe aus
  22. *    SID-Registern nur simuliert
  23. *  - Die Power-LED ist mit dem Reset-Eingang des SID verbunden,
  24. *    d.h. ein kurzes Aus- und Einschalten der LED setzt den SID
  25. *    zurück
  26. *
  27. * PlaySID:
  28. *  - Da die playsid.library keinen Befehl zum direkten Setzen von SID-
  29. *    Registern hat, wird ein Trick angewendet: Es wird ein Dummy-Modul
  30. *    installiert, dessen Play-Routine nur die Aufgabe hat, ein einziges
  31. *    SID-Register zu setzen. Schreibt der Prozessor in ein SID-Register,
  32. *    werden Registernummer und Wert in die Play-Routine im C64-RAM der
  33. *    playsid.library geschrieben und über ForwardSong ein Aufruf der
  34. *    Play-Routine erzwungen
  35. *
  36.  
  37.         MACHINE    68020
  38.  
  39.         INCLUDE    "exec/types.i"
  40.         INCLUDE    "exec/macros.i"
  41.         INCLUDE    "exec/nodes.i"
  42.         INCLUDE    "libraries/playsidbase.i"
  43.         INCLUDE    "libraries/playsid_lib.i"
  44.         INCLUDE    "hardware/intbits.i"
  45.  
  46.         XREF    _SysBase
  47.         XREF    _GfxBase
  48.         XREF    _SID6581Base
  49.         XREF    _PlaySidBase
  50.  
  51.         XREF    Random
  52.  
  53.         XDEF    Reset6581
  54.         XDEF    ReadFrom6581
  55.         XDEF    WriteTo6581
  56.         XDEF    _PauseSound
  57.         XDEF    _ResumeSound
  58.         XDEF    _GetSIDDump
  59.         XDEF    InitSID
  60.         XDEF    ExitSID
  61.         XDEF    ChangedSIDPrefs
  62.         XDEF    SIDType        ;Prefs
  63.  
  64.         SECTION    "text",CODE
  65.  
  66. *
  67. * Definitionen
  68. *
  69.  
  70. ; SIDType
  71. SIDTYPE_OFF    = 0    ;Audio-Ausgabe aus
  72. SIDTYPE_CARD    = 1    ;SID-Karte
  73. SIDTYPE_A64    = 2    ;6581sid.library
  74. SIDTYPE_PSID    = 3    ;playsid.library
  75.  
  76. ; 6581sid.library
  77. SID_AllocSID    = -30
  78. SID_FreeSID    = -36
  79. SID_Interrupt    = -42
  80. SID_Initialize    = -48
  81. SID_ResetSID    = -54
  82. SID_IRQOnOff    = -60
  83. SID_ReadReg    = -72
  84. SID_WriteReg    = -78
  85.  
  86. ; SID Handle Struktur
  87. sid_Enabled    = 4
  88. sid_Filter    = 5
  89. sid_60Hz    = 6
  90. sid_RingQual    = 7
  91. sid_SyncQual    = 8
  92. sid_ADSRQual    = 13
  93. sid_IRQRate    = 18
  94.  
  95.  
  96. **
  97. ** SID-Emulation starten
  98. **
  99.  
  100. InitSID        move.w    SIDType,CurrentSIDType
  101.         bsr    OpenSID
  102.         st.b    SIDInited
  103.         rts
  104.  
  105.  
  106. **
  107. ** SID-Emulation beenden
  108. **
  109.  
  110. ExitSID        tst.b    SIDInited
  111.         beq    1$
  112.         bsr    CloseSID
  113. 1$        rts
  114.  
  115.  
  116. **
  117. ** SID-Einstellungen wurde verändert
  118. **
  119.  
  120. ; Schließen und neu öffnen, wenn sich die Einstellungen geändert haben
  121. ChangedSIDPrefs    move.w    SIDType,d0
  122.         cmp.w    CurrentSIDType,d0
  123.         beq    1$
  124.  
  125.         bsr    CloseSID
  126.         move.w    SIDType,CurrentSIDType
  127.         bsr    OpenSID
  128.  
  129.         moveq    #0,d2
  130. 2$        move.w    d2,d0
  131.         move.b    (Registers,d0.w),d1
  132.         bsr    WriteTo6581    ;SID-Register neu laden
  133.         addq.w    #1,d2
  134.         cmp.w    #24,d2
  135.         bne    2$
  136. 1$        rts
  137.  
  138.  
  139. *
  140. * Alles für SID-Emulation mit CurrentSIDType vorbereiten
  141. *
  142.  
  143. OpenSID        cmp.w    #SIDTYPE_A64,CurrentSIDType
  144.         beq    OpenA64
  145.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  146.         beq    OpenPSID
  147.         rts
  148.  
  149. OpenA64        move.l    _SID6581Base,d0        ;6581sid.library offen?
  150.         beq    1$
  151.  
  152.         move.l    a6,-(sp)        ;Ja, SIDHandle holen
  153.         move.l    d0,a6
  154.         jsr    SID_AllocSID(a6)
  155.         move.l    d0,SIDHandle
  156.         beq    2$
  157.  
  158.         move.l    d0,a1            ;Parameter setzen
  159.         st.b    sid_Enabled(a1)
  160.         clr.b    sid_Filter(a1)
  161.         st.b    sid_60Hz(a1)
  162.         move.b    #48,sid_RingQual(a1)
  163.         move.b    #48,sid_SyncQual(a1)
  164.         move.b    #48,sid_ADSRQual(a1)
  165.         move.w    #60,sid_IRQRate(a1)
  166.         jsr    SID_Initialize(a6)
  167.  
  168.         move.l    SIDHandle,a1        ;SID anschalten
  169.         moveq    #0,d0
  170.         jsr    SID_IRQOnOff(a6)
  171.  
  172.         move.l    _SysBase,a6        ;VBI einrichten
  173.         lea    VBInterrupt,a1
  174.         moveq    #INTB_VERTB,d0
  175.         JSRLIB    AddIntServer
  176.  
  177. 2$        move.l    (sp)+,a6
  178. 1$        rts
  179.  
  180. OpenPSID    clr.b    PSIDOpened
  181.  
  182.         move.l    _PlaySidBase,d0        ;playsid.library offen?
  183.         beq    1$
  184.  
  185.         move.l    a6,-(sp)
  186.         move.l    d0,a6            ;Ja, Resourcen belegen
  187.         jsr    _LVOAllocEmulResource(a6)
  188.         tst.l    d0
  189.         bne    2$
  190.  
  191.         lea    PSIDHeader,a0        ;"Modul" setzen
  192.         move.l    a0,a1
  193.         move.l    #PSIDEnd-PSIDHeader,d0
  194.         jsr    _LVOSetModule(a6)
  195.  
  196.         moveq    #1,d0            ;Und starten
  197.         jsr    _LVOStartSong(a6)
  198.         tst.l    d0
  199.         beq    3$
  200.  
  201.         jsr    _LVOFreeEmulResource(a6) ;Nicht gelungen
  202.         bra    2$
  203.  
  204. 3$        bset    #1,$bfe001        ;Filter aus
  205.         st.b    PSIDOpened
  206.  
  207. 2$        move.l    (sp)+,a6
  208. 1$        rts
  209.  
  210.  
  211. *
  212. * SID-Emulation mit CurrentSIDType beenden
  213. *
  214.  
  215. CloseSID    cmp.w    #SIDTYPE_A64,CurrentSIDType
  216.         beq    CloseA64
  217.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  218.         beq    ClosePSID
  219.         rts
  220.  
  221. CloseA64    move.l    SIDHandle,d0
  222.         beq    1$
  223.  
  224.         move.l    a6,-(sp)
  225.         move.l    _SID6581Base,a6        ;SID abschalten
  226.         move.l    d0,a1
  227.         moveq    #-1,d0
  228.         jsr    SID_IRQOnOff(a6)
  229.  
  230.         move.l    _SysBase,a6        ;VBI entfernen
  231.         lea    VBInterrupt,a1
  232.         moveq    #INTB_VERTB,d0
  233.         JSRLIB    RemIntServer
  234.  
  235.         move.l    _SID6581Base,a6
  236.         move.l    SIDHandle,a1        ;Und SIDHandle freigeben
  237.         jsr    SID_FreeSID(a6)
  238.         clr.l    SIDHandle
  239.         move.l    (sp)+,a6
  240. 1$        rts
  241.  
  242. ClosePSID    tst.b    PSIDOpened
  243.         beq    1$
  244.  
  245.         move.l    a6,-(sp)
  246.         move.l    _PlaySidBase,a6
  247.         jsr    _LVOStopSong(a6)    ;Alles freigeben
  248.         jsr    _LVOFreeEmulResource(a6)
  249.         bclr    #1,$bfe001        ;Filter an
  250.         clr.b    PSIDOpened
  251.         move.l    (sp)+,a6
  252. 1$        rts
  253.  
  254.  
  255. *
  256. * Interrupt-Routine
  257. * a1: SIDHandle
  258. *
  259.  
  260. IntProc        move.l    _SID6581Base,a6
  261.         jsr    SID_Interrupt(a6)
  262.         moveq    #0,d0            ;Nächsten Server aufrufen
  263.         rts
  264.  
  265.  
  266. **
  267. ** Sound stummschalten
  268. **
  269.  
  270. _PauseSound    cmp.w    #SIDTYPE_A64,CurrentSIDType
  271.         beq    PauseA64
  272.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  273.         beq    PausePSID
  274.         rts
  275.  
  276. PauseA64    move.l    SIDHandle,d0
  277.         beq    1$
  278.         move.l    a6,-(sp)
  279.         move.l    _SID6581Base,a6
  280.         move.l    d0,a1
  281.         moveq    #-1,d0
  282.         jsr    SID_IRQOnOff(a6)
  283.         move.l    (sp)+,a6
  284. 1$        rts
  285.  
  286. PausePSID    tst.b    PSIDOpened
  287.         beq    1$
  288.         move.l    a6,-(sp)
  289.         move.l    _PlaySidBase,a6
  290.         jsr    _LVOPauseSong(a6)
  291.         move.l    (sp)+,a6
  292. 1$        rts
  293.  
  294.  
  295. **
  296. ** Sound wieder laut machen
  297. **
  298.  
  299. _ResumeSound    cmp.w    #SIDTYPE_A64,CurrentSIDType
  300.         beq    ResumeA64
  301.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  302.         beq    ResumePSID
  303.         rts
  304.  
  305. ResumeA64    move.l    SIDHandle,d0
  306.         beq    1$
  307.         move.l    a6,-(sp)
  308.         move.l    _SID6581Base,a6
  309.         move.l    d0,a1
  310.         moveq    #0,d0
  311.         jsr    SID_IRQOnOff(a6)
  312.         move.l    (sp)+,a6
  313. 1$        rts
  314.  
  315. ResumePSID    tst.b    PSIDOpened
  316.         beq    1$
  317.         move.l    a6,-(sp)
  318.         move.l    _PlaySidBase,a6
  319.         jsr    _LVOContinueSong(a6)
  320.         move.l    (sp)+,a6
  321. 1$        rts
  322.  
  323.  
  324. **
  325. ** SID zurücksetzen
  326. **
  327.  
  328. Reset6581    lea    Registers,a0
  329.         moveq    #32/4-1,d0
  330. 1$        clr.l    (a0)+
  331.         dbra    d0,1$
  332.         clr.b    LastSIDByte
  333.  
  334.         cmp.w    #SIDTYPE_CARD,CurrentSIDType
  335.         beq    ResetCard
  336.         cmp.w    #SIDTYPE_A64,CurrentSIDType
  337.         beq    ResetA64
  338.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  339.         beq    ResetPSID
  340.         rts
  341.  
  342. ResetCard    move.l    a6,-(sp)
  343.         move.l    _GfxBase,a6
  344.         JSRLIB    WaitTOF
  345.         bset    #1,$bfe001    ;LED aus
  346.         JSRLIB    WaitTOF
  347.         bclr    #1,$bfe001    ;LED an
  348.         move.l    (sp)+,a6
  349.         rts
  350.  
  351. ResetA64    move.l    SIDHandle,d0
  352.         beq    1$
  353.         move.l    a6,-(sp)
  354.         move.l    _SID6581Base,a6
  355.         move.l    d0,a1
  356.         jsr    SID_ResetSID(a6)
  357.         move.l    (sp)+,a6
  358. 1$        rts
  359.  
  360. ResetPSID    tst.b    PSIDOpened
  361.         beq    1$
  362.         move.l    a6,-(sp)
  363.         move.l    _PlaySidBase,a6
  364.         jsr    _LVOStopSong(a6)
  365.         moveq    #1,d0
  366.         jsr    _LVOStartSong(a6)
  367.         move.l    (sp)+,a6
  368. 1$        rts
  369.  
  370.  
  371. **
  372. ** SID-Status in Datenstruktur schreiben
  373. **
  374.  
  375. _GetSIDDump    move.l    4(sp),a1
  376.         lea    Registers,a0
  377.  
  378.         moveq    #24,d0        ;freq_lo_1 bis mode_vol
  379. 1$        move.b    (a0)+,(a1)+
  380.         dbra    d0,1$
  381.  
  382.         st    (a1)+        ;pot_x
  383.         st    (a1)+        ;pot_y
  384.         clr.b    (a1)+        ;osc_3
  385.         clr.b    (a1)        ;env_3
  386.         rts
  387.  
  388.  
  389. **
  390. ** Aus einem SID-Register lesen
  391. ** d0.w: Registernummer ($00-$1f)
  392. ** Rückgabe: d0.b: Byte
  393. **
  394. ** Darf das obere Wort von d0 und d1 nicht verändern!
  395. **
  396.  
  397. ReadFrom6581    cmp.b    #$19,d0
  398.         beq    ReadFF
  399.         cmp.b    #$1a,d0
  400.         beq    ReadFF
  401.         cmp.b    #$1b,d0
  402.         beq    ReadRnd
  403.         cmp.b    #$1c,d0
  404.         beq    ReadRnd
  405.         move.b    LastSIDByte,d0
  406.         rts
  407.  
  408. ReadFF        move.b    #-1,d0        ;A/D-Wandler
  409.         clr.b    LastSIDByte
  410.         rts
  411.  
  412. ReadRnd        jsr    Random
  413.         moveq    #0,d1        ;MSW löschen
  414.         clr.b    LastSIDByte
  415.         rts
  416.  
  417.  
  418. **
  419. ** In ein SID-Register schreiben
  420. ** d0.w: Registernummer ($00-$1f)
  421. ** d1.b: Byte
  422. **
  423. ** Darf das obere Wort von d0 und d1 nicht verändern!
  424. **
  425.  
  426. WriteTo6581    move.b    d1,(Registers,d0.w)
  427.         move.b    d1,LastSIDByte
  428.         cmp.w    #SIDTYPE_CARD,CurrentSIDType
  429.         beq    WriteCard
  430.         cmp.w    #SIDTYPE_A64,CurrentSIDType
  431.         beq    WriteA64
  432.         cmp.w    #SIDTYPE_PSID,CurrentSIDType
  433.         beq    WritePSID
  434.         rts
  435.  
  436. WriteCard    lea    $a00001,a0    ;SID-Karte
  437.         move.b    d1,(a0,d0.w*2)
  438.         rts
  439.  
  440. WriteA64    tst.l    SIDHandle
  441.         beq    1$
  442.         move.l    a6,-(sp)
  443.         move.l    _SID6581Base,a6
  444.         move.l    SIDHandle,a1    ;d0: Regnum, d1: Byte
  445.         jsr    SID_WriteReg(a6)
  446.         move.l    (sp)+,a6
  447.         moveq    #0,d0
  448.         moveq    #0,d1
  449. 1$        rts
  450.  
  451. WritePSID    tst.b    PSIDOpened
  452.         beq    1$
  453.         move.l    a6,-(sp)
  454.         move.l    _PlaySidBase,a6
  455.         move.l    $15a(a6),a0    ;Code im C64-RAM der playsid.library ändern
  456.         move.b    d0,$1004(a0)
  457.         move.b    d1,$1002(a0)
  458.         moveq    #1,d0        ;Aufruf der Play-Routine erzwingen
  459.         jsr    _LVOForwardSong(a6)
  460.         move.l    (sp)+,a6
  461.         moveq    #0,d0
  462.         moveq    #0,d1
  463. 1$        rts
  464.  
  465.  
  466. **
  467. ** SID-Register (nur als Backup für SAM und Snapshots)
  468. **
  469.  
  470. Registers    ds.b    32
  471. LastSIDByte    ds.b    1    ;Letztes in den SID geschriebenes Byte
  472.         CNOP    0,4
  473.  
  474.  
  475. **
  476. ** Konstanten
  477. **
  478.  
  479. IntName        dc.b    "Frodo SID VBI",0
  480.  
  481.  
  482. **
  483. ** Initialisierte Daten
  484. **
  485.  
  486.         SECTION    "DATA",DATA
  487.  
  488. VBInterrupt    dc.l    0,0
  489.         dc.b    NT_INTERRUPT,0
  490.         dc.l    IntName
  491. SIDHandle    dc.l    0    ;Handle für die 6581sid.library und Flag, daß sie verfügbar ist
  492.         dc.l    IntProc
  493.  
  494. SIDType        dc.w    0    ;Prefs: Art der SID-Emulation
  495.  
  496. PSIDHeader    dc.b    "PSID"    ;Dummy-Modul-Header für playsid.library
  497.         dc.w    2
  498.         dc.w    PSIDHeaderEnd-PSIDHeader
  499.         dc.w    $1000    ;Load
  500.         dc.w    $1000    ;Init
  501.         dc.w    $1001    ;Play
  502.         dc.w    1
  503.         dc.w    1
  504.         dc.l    0
  505.         ds.b    HEADERINFO_SIZE
  506.         ds.b    HEADERINFO_SIZE
  507.         ds.b    HEADERINFO_SIZE
  508.         dc.w    0
  509.         dc.l    0
  510. PSIDHeaderEnd
  511.                     ;Init:
  512.         dc.b    $60        ; rts
  513.  
  514.                     ;Play:
  515.         dc.b    $a9,0        ; lda #xx
  516.         dc.b    $8d,0,$d4    ; sta $d4xx
  517.         dc.b    $60        ; rts
  518. PSIDEnd
  519.  
  520.  
  521. **
  522. ** Nicht initialisierte Daten
  523. **
  524.  
  525.         SECTION    "BSS",BSS
  526.  
  527. CurrentSIDType    ds.w    1    ;Augenblicklicher SID-Typ
  528.  
  529. SIDInited    ds.b    1    ;Flag: InitSID wurde aufgerufen
  530. PSIDOpened    ds.b    1    ;Flag: playsid.library ist initialisiert
  531.  
  532.         END
  533.